home *** CD-ROM | disk | FTP | other *** search
- /*
- ** hc.c
- **
- ** Help-Compiler, Help compiler utility.
- ** Compile with any memory model but large data (compact
- ** or large) provides more run-time memory.
- **
- ** Pictor, Version 1.51, Copyright (c) 1992-94 SoftCircuits
- ** Redistributed by permission.
- */
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <ctype.h>
- #include <string.h>
-
- #include <pictor.h>
- #include <compress.h>
-
- #define MAX_LABEL 80
- struct item {
- char label[MAX_LABEL + 1];
- long offset;
- unsigned comp_size;
- unsigned uncomp_size;
- struct item *next;
- };
-
- struct item *first = NULL;
- struct item **array;
- char signature[] = "PICTORHLP00";
- unsigned num_topics,max_comp = 0,max_uncomp = 0;
- unsigned comp_size,uncomp_size;
- unsigned errors = 0,warnings = 0;
- unsigned line = 0;
- char *whtspc = " \t\n";
- char buffer[BUFSIZ];
- char *outfile;
-
- #define WARN 0x00
- #define ERROR 0x01
- #define FATAL 0x02
-
- /*
- ** displays diagnostic and counts error
- */
- void error(char *msg,int type)
- {
- static char *error_types[] = {
- "Warning",
- "Error",
- "Fatal error",
- };
-
- printf("%s : ",error_types[type]);
- if(line != 0) printf("Line %d : ",line);
- printf("%s\n",msg);
-
- if(type == WARN)
- warnings++;
- else
- errors++;
-
- } /* error */
-
- /*
- ** sets dos errorlevel to number of errors, closes all files and exits
- ** this function deletes the temporary file and if errors have occured,
- ** deletes the output file
- */
- void terminate(void)
- {
- fcloseall();
-
- if(errors) {
- printf("\nOutput file not created\n");
- unlink(outfile);
- }
- exit(errors);
-
- } /* terminate */
-
- /*
- ** compare routine for qsort()
- */
- int compare(const void *elem1,const void *elem2)
- {
- return(stricmp(*(char **)elem1,*(char **)elem2));
-
- } /* compare */
-
- /*
- ** builds compressed output file from input file
- */
- void create_output(char *filename,FILE *tmp_stream)
- {
- int len;
- unsigned i;
- FILE *stream;
- NODE *root_node;
- struct item *curr;
- void *inbuff,*outbuff;
- long fpos = 0,fpos2 = 0;
-
- /* compute most efficient compression code tree */
- rewind(tmp_stream);
- root_node = gettree(tmp_stream);
- if(root_node == NULL) {
- error("Insufficient memory",FATAL);
- terminate();
- }
-
- /* open output file */
- stream = fopen(filename,"wb");
- if(stream == NULL) {
- error("Unable to create output file",FATAL);
- terminate();
- }
- /* write signature */
- fwrite(signature,sizeof(char),sizeof(signature),stream);
-
- /* write code tree */
- len = writetree(root_node,(BYTE *)buffer);
- putw(len,stream);
- fwrite(buffer,sizeof(char),len,stream);
-
- /* make room for file offset pointer */
- fpos = ftell(stream);
- fwrite(&fpos,sizeof(long),1,stream);
-
- /* allocate compression buffers */
- inbuff = malloc(max_uncomp);
- outbuff = malloc(max_uncomp + 512);
- if(inbuff == NULL || outbuff == NULL) {
- error("Insufficient memory",FATAL);
- terminate();
- }
-
- /* write compressed help text */
- rewind(tmp_stream);
- for(i = 0,curr = first;curr != NULL;i++,curr = curr->next) {
- fread(inbuff,sizeof(char),curr->uncomp_size,tmp_stream);
- curr->comp_size = compress(inbuff,curr->uncomp_size,outbuff,root_node);
- if(curr->comp_size > max_comp)
- max_comp = curr->comp_size;
- curr->offset = ftell(stream);
- putw(curr->comp_size,stream);
- putw(curr->uncomp_size,stream);
- fwrite(outbuff,sizeof(char),curr->comp_size,stream);
- }
-
- fpos2 = ftell(stream);
-
- /* */
- putw(num_topics,stream);
- putw(max_comp,stream);
- putw(max_uncomp,stream);
-
- /* write sorted file offsets for each topics */
- for(i = 0;i < num_topics;i++) {
- fwrite(&(array[i]->offset),sizeof(array[0]->offset),1,stream);
- }
-
- /* */
- inbuff = realloc(inbuff,uncomp_size);
- outbuff = realloc(outbuff,uncomp_size + 512);
- if(inbuff == NULL || outbuff == NULL) {
- error("Insufficient memory",FATAL);
- terminate();
- }
-
- /* */
- fread(inbuff,sizeof(char),uncomp_size,tmp_stream);
-
- /* compress topic labels */
- comp_size = compress(inbuff,uncomp_size,outbuff,root_node);
-
- /* */
- putw(comp_size,stream);
- putw(uncomp_size,stream);
-
- /* write compressed topic labels to output file */
- fwrite(outbuff,sizeof(char),comp_size,stream);
-
- /* */
- fseek(stream,fpos,SEEK_SET);
- fwrite(&fpos2,sizeof(fpos2),1,stream);
-
- fclose(tmp_stream);
- fclose(stream);
-
- } /* create_output */
-
- /*
- ** parses the input file
- ** returns a pointer to the temporary file stream
- */
- FILE *read_input(char *filename)
- {
- FILE *stream,*tmp_stream;
- struct item *new,*curr = NULL;
- int in_topic = FALSE;
- char *cptr;
-
- /* open input file */
- if((stream = fopen(filename,"rt")) == NULL) {
- error("Unable to open input file",FATAL);
- terminate();
- }
- /* create temporary file */
- if((tmp_stream = tmpfile()) == NULL) {
- error("Unable to create temporary file",FATAL);
- terminate();
- }
- for(line = 1;fgets(buffer,BUFSIZ,stream);line++) {
- /* find first non-space character */
- cptr = (buffer + strspn(buffer,whtspc));
-
- if(*cptr == '@') { /* compiler directive */
- cptr = strtok(cptr + 1,whtspc);
- if(cptr == NULL) {
- error("Compiler directive expected following '@'",ERROR);
- }
- else if(!strcmpi(cptr,"BEGIN")) { /* new topic */
- if(!in_topic) {
- if((new = malloc(sizeof(struct item))) == NULL) {
- error("Insufficient memory",FATAL);
- terminate();
- }
- if(first == NULL)
- first = new;
- else
- curr->next = new;
- curr = new;
- curr->next = NULL;
- curr->label[0] = '\0';
- curr->uncomp_size = 0;
-
- cptr = strtok(NULL,"");
- if(cptr == NULL || *(cptr += strspn(cptr,whtspc)) == '\0') {
- error("@BEGIN must be followed by topic label",ERROR);
- }
- else {
- /* strip trailing whitespace */
- while(isspace(cptr[strlen(cptr) - 1]))
- cptr[strlen(cptr) - 1] = '\0';
-
- if(strlen(cptr) > MAX_LABEL) {
- error("Topic label too long, truncating",WARN);
- cptr[MAX_LABEL] = '\0';
- }
- strcpy(curr->label,cptr);
-
- /* search for duplicate labels */
- for(new = first;new->next != NULL;new = new->next) {
- if(!stricmp(cptr,new->label)) {
- error("Topic already defined",ERROR);
- break;
- }
- }
- }
- in_topic = TRUE;
- }
- else error("@BEGIN before @END",ERROR);
- }
- else if(!strcmpi(cptr,"END")) {
- if(in_topic) {
- if(curr->uncomp_size > max_uncomp)
- max_uncomp = curr->uncomp_size;
- num_topics++;
- in_topic = FALSE;
-
- if(strtok(NULL,whtspc) != NULL)
- error("Extra characters ignored",WARN);
- }
- else error("@END before @BEGIN",ERROR);
- }
- else error("Unknown compiler directive",ERROR);
- }
- else {
- if(in_topic) {
- fwrite(buffer,sizeof(char),strlen(buffer),tmp_stream);
- curr->uncomp_size += strlen(buffer);
- }
- else if(*cptr != '\0' && *cptr != ';')
- error("Text outside @BEGIN/@END",ERROR);
- }
- }
- if(ferror(stream)) {
- error("Error reading input file",FATAL);
- terminate();
- }
- else if(in_topic) {
- error("Unexpected end-of-file",ERROR);
- if(curr->uncomp_size > max_uncomp)
- max_uncomp = curr->uncomp_size;
- num_topics++;
- }
- fclose(stream);
-
- /* indicate we're no longer processing input file */
- line = 0;
-
- return(tmp_stream);
-
- } /* read_input */
-
- /*
- ** here's main()
- */
- void main(int argc,char *argv[])
- {
- unsigned i,len;
- FILE *tmp_stream;
- struct item *curr;
-
- printf("HC - Help Compiler, Version 1.51,"
- " Copyright (c) 1992-94 SoftCircuits\n");
- printf("Redistributed by permission.\n\n");
-
- if(argc != 3) {
- printf("Usage: HC <input-file> <output-file>\n");
- terminate();
- }
- outfile = argv[2];
-
- /* process input file */
- tmp_stream = read_input(argv[1]);
-
- if(num_topics == 0) {
- error("Input file contains no help topics",FATAL);
- terminate();
- }
-
- /* build array and sort array of pointers to items */
- if((array = malloc(sizeof(struct item *) * num_topics)) == NULL) {
- error("Insufficient memory",FATAL);
- terminate();
- }
- for(i = 0,curr = first;curr != NULL;i++,curr = curr->next) {
- array[i] = curr;
- }
- qsort(array,num_topics,sizeof(struct item *),compare);
-
- /* write sorted topic labels to temporary file so */
- /* they'll be included in the compression code tree */
- for(uncomp_size = 0,i = 0;i < num_topics;i++) {
- len = (strlen(array[i]->label) + 1);
- fwrite(array[i]->label,sizeof(char),len,tmp_stream);
- uncomp_size += len;
- }
- create_output(argv[2],tmp_stream);
-
- printf("%9d Error(s)\n",errors);
- printf("%9d Warning(s)\n",warnings);
- terminate();
-
- } /* main */
-
-
-